using ConsoleApi.Models;
using ConsoleApi.Services.Interfaces;
using Microsoft.Extensions.Options;
using System.Text.Json;

namespace ConsoleApi.Services;

/// <summary>
/// 真实天气服务实现 - 使用OpenWeatherMap API
/// </summary>
public class RealWeatherService : IRealWeatherService
{
    private readonly ILogger<RealWeatherService> _logger;
    private readonly HttpClient _httpClient;
    private readonly OpenWeatherMapConfig _config;

    public RealWeatherService(ILogger<RealWeatherService> logger, HttpClient httpClient, IOptions<OpenWeatherMapConfig> config)
    {
        _logger = logger;
        _httpClient = httpClient;
        _config = config.Value;
    }

    public async Task<WeatherData> GetWeatherByCityAsync(string city)
    {
        _logger.LogInformation("获取城市天气信息: {City}", city);
        
        try
        {
            // 将中文城市名转换为英文
            var englishCityName = TranslateCityName(city);
            _logger.LogInformation("转换后的城市名: {EnglishCityName}", englishCityName);
            
            // 获取当前天气
            var currentWeatherUrl = $"{_config.BaseUrl}/weather?q={englishCityName}&appid={_config.ApiKey}&units={_config.Units}&lang={_config.Language}";
            var currentResponse = await _httpClient.GetAsync(currentWeatherUrl);
            
            if (!currentResponse.IsSuccessStatusCode)
            {
                _logger.LogError("获取当前天气失败: {StatusCode}", currentResponse.StatusCode);
                throw new Exception($"获取天气失败: {currentResponse.StatusCode}");
            }
            
            var currentJson = await currentResponse.Content.ReadAsStringAsync();
            var currentData = JsonSerializer.Deserialize<OpenWeatherMapCurrentResponse>(currentJson);
            
            if (currentData == null)
            {
                throw new Exception("解析当前天气数据失败");
            }
            
            // 获取天气预报
            var forecastUrl = $"{_config.BaseUrl}/forecast?q={englishCityName}&appid={_config.ApiKey}&units={_config.Units}&lang={_config.Language}";
            var forecastResponse = await _httpClient.GetAsync(forecastUrl);
            
            List<ForecastDay> forecast = new();
            if (forecastResponse.IsSuccessStatusCode)
            {
                var forecastJson = await forecastResponse.Content.ReadAsStringAsync();
                var forecastData = JsonSerializer.Deserialize<OpenWeatherMapForecastResponse>(forecastJson);
                
                if (forecastData != null)
                {
                    // 按天分组，获取每天的最高最低温度和主要天气
                    var dailyGroups = forecastData.List
                        .GroupBy(x => DateTimeOffset.FromUnixTimeSeconds(x.Dt).Date)
                        .Take(7)
                        .ToList();
                    
                    foreach (var dayGroup in dailyGroups)
                    {
                        var dayDate = dayGroup.Key;
                        var dayItems = dayGroup.ToList();
                        
                        // 计算当天的最高最低温度
                        var maxTemp = dayItems.Max(x => x.Main.TempMax);
                        var minTemp = dayItems.Min(x => x.Main.TempMin);
                        
                        // 取中午12点或最接近中午的数据作为主要天气描述
                        var noonItem = dayItems
                            .OrderBy(x => Math.Abs(DateTimeOffset.FromUnixTimeSeconds(x.Dt).Hour - 12))
                            .FirstOrDefault();
                        
                        var weatherText = noonItem != null 
                            ? TranslateWeatherDescription(noonItem.Weather.FirstOrDefault()?.Description ?? "")
                            : "未知";
                        
                        var windDir = noonItem != null 
                            ? GetWindDirection(noonItem.Wind.Deg)
                            : "未知风向";
                        
                        var windSpeed = noonItem != null 
                            ? noonItem.Wind.Speed
                            : 0;
                        
                        var humidity = noonItem != null 
                            ? noonItem.Main.Humidity
                            : 0;
                        
                        // 取当天的最高降水概率
                        var maxPrecip = dayItems.Max(x => x.Pop);
                        
                        forecast.Add(new ForecastDay
                        {
                            Date = dayDate,
                            MaxTemp = maxTemp,
                            MinTemp = minTemp,
                            Text = weatherText,
                            WindDir = windDir,
                            WindSpeed = windSpeed,
                            Humidity = humidity,
                            Precip = (int)(maxPrecip * 100) // 降水概率转换为百分比
                        });
                    }
                }
            }
            
            var weatherData = new WeatherData
            {
                City = currentData.Name,
                LastUpdated = DateTimeOffset.FromUnixTimeSeconds(currentData.Dt).DateTime,
                Current = new CurrentWeather
                {
                    Temp = currentData.Main.Temp,
                    Text = TranslateWeatherDescription(currentData.Weather.FirstOrDefault()?.Description ?? ""),
                    WindSpeed = currentData.Wind.Speed,
                    WindDir = GetWindDirection(currentData.Wind.Deg),
                    Humidity = currentData.Main.Humidity,
                    Pressure = currentData.Main.Pressure,
                    Vis = currentData.Visibility / 1000.0
                },
                Forecast = forecast
            };
            
            return weatherData;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取城市天气失败: {City}", city);
            throw;
        }
    }

    /// <summary>
    /// 将中文城市名转换为英文
    /// </summary>
    private string TranslateCityName(string chineseCityName)
    {
        return chineseCityName.ToLower() switch
        {
            "北京" => "Beijing",
            "上海" => "Shanghai",
            "广州" => "Guangzhou",
            "深圳" => "Shenzhen",
            "杭州" => "Hangzhou",
            "南京" => "Nanjing",
            "武汉" => "Wuhan",
            "成都" => "Chengdu",
            "重庆" => "Chongqing",
            "西安" => "Xian",
            "天津" => "Tianjin",
            "苏州" => "Suzhou",
            "青岛" => "Qingdao",
            "大连" => "Dalian",
            "厦门" => "Xiamen",
            "宁波" => "Ningbo",
            "无锡" => "Wuxi",
            "长沙" => "Changsha",
            "郑州" => "Zhengzhou",
            "济南" => "Jinan",
            "哈尔滨" => "Harbin",
            "沈阳" => "Shenyang",
            "长春" => "Changchun",
            "石家庄" => "Shijiazhuang",
            "太原" => "Taiyuan",
            "呼和浩特" => "Hohhot",
            "银川" => "Yinchuan",
            "西宁" => "Xining",
            "兰州" => "Lanzhou",
            "乌鲁木齐" => "Urumqi",
            "拉萨" => "Lhasa",
            "昆明" => "Kunming",
            "贵阳" => "Guiyang",
            "南宁" => "Nanning",
            "海口" => "Haikou",
            "福州" => "Fuzhou",
            "南昌" => "Nanchang",
            "合肥" => "Hefei",
            "珠海" => "Zhuhai",
            "佛山" => "Foshan",
            "东莞" => "Dongguan",
            "中山" => "Zhongshan",
            "江门" => "Jiangmen",
            "肇庆" => "Zhaoqing",
            "惠州" => "Huizhou",
            "汕头" => "Shantou",
            "潮州" => "Chaozhou",
            "揭阳" => "Jieyang",
            "汕尾" => "Shanwei",
            "河源" => "Heyuan",
            "梅州" => "Meizhou",
            "韶关" => "Shaoguan",
            "清远" => "Qingyuan",
            "阳江" => "Yangjiang",
            "茂名" => "Maoming",
            "湛江" => "Zhanjiang",
            "云浮" => "Yunfu",
            _ => chineseCityName // 如果没有找到匹配，返回原名称
        };
    }

    /// <summary>
    /// 翻译天气描述为中文
    /// </summary>
    private string TranslateWeatherDescription(string description)
    {
        return description.ToLower() switch
        {
            "clear sky" => "晴天",
            "few clouds" => "少云",
            "scattered clouds" => "散云",
            "broken clouds" => "多云",
            "overcast clouds" => "阴天",
            "light rain" => "小雨",
            "moderate rain" => "中雨",
            "heavy rain" => "大雨",
            "very heavy rain" => "暴雨",
            "extreme rain" => "特大暴雨",
            "light snow" => "小雪",
            "moderate snow" => "中雪",
            "heavy snow" => "大雪",
            "sleet" => "雨夹雪",
            "mist" => "薄雾",
            "fog" => "雾",
            "haze" => "霾",
            "thunderstorm" => "雷暴",
            "drizzle" => "毛毛雨",
            "shower rain" => "阵雨",
            "rain and snow" => "雨夹雪",
            _ => description
        };
    }

    /// <summary>
    /// 根据角度获取风向
    /// </summary>
    private string GetWindDirection(int degrees)
    {
        // 标准化角度到0-360范围
        degrees = ((degrees % 360) + 360) % 360;
        
        if (degrees >= 337.5 || degrees < 22.5)
            return "北风";
        else if (degrees >= 22.5 && degrees < 67.5)
            return "东北风";
        else if (degrees >= 67.5 && degrees < 112.5)
            return "东风";
        else if (degrees >= 112.5 && degrees < 157.5)
            return "东南风";
        else if (degrees >= 157.5 && degrees < 202.5)
            return "南风";
        else if (degrees >= 202.5 && degrees < 247.5)
            return "西南风";
        else if (degrees >= 247.5 && degrees < 292.5)
            return "西风";
        else if (degrees >= 292.5 && degrees < 337.5)
            return "西北风";
        else
            return "未知风向";
    }

    public async Task<List<string>> GetWeatherAlertsAsync(string city)
    {
        _logger.LogInformation("获取城市天气预警: {City}", city);
        return new List<string>();
    }

    public async Task<AirQualityData> GetAirQualityAsync(string city)
    {
        _logger.LogInformation("获取城市空气质量: {City}", city);
        return new AirQualityData
        {
            City = city,
            Aqi = 75,
            Level = "良",
            Primary = "PM2.5",
            UpdateTime = DateTime.Now
        };
    }
} 